Add a gtk-im-module GTK setting
authorMatthias Clasen <mclasen@redhat.com>
Tue, 18 Dec 2007 03:24:17 +0000 (03:24 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Tue, 18 Dec 2007 03:24:17 +0000 (03:24 +0000)
2007-12-17  Matthias Clasen  <mclasen@redhat.com>

        * gtk/gtksettings.c: Add a gtk-im-module GTK setting
        * gdk/win32/gdkproperty-win32.c:
        * gdk/x11/gdksettings.c: ...and back it by a Gtk/IMModule X setting.

        * gtk/gtkimmodule.[hc]:
        * gtk/gtkimmulticontext.[hc]: When determining the default context,
        look at the gtk-im-module setting, and listen for changes to the
        setting.  (#502446, Akira Tagoh)

svn path=/trunk/; revision=19195

ChangeLog
docs/reference/ChangeLog
docs/reference/gtk/running.sgml
gdk/win32/gdkproperty-win32.c
gdk/x11/gdksettings.c
gtk/gtkimmodule.c
gtk/gtkimmodule.h
gtk/gtkimmulticontext.c
gtk/gtkimmulticontext.h
gtk/gtksettings.c

index 6d6ec01d9bd29f2398dbbbe5867a456b09367297..68be1d1fa16a3ede627a48b109c4c8c1aca5af1e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-12-17  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtksettings.c: Add a gtk-im-module GTK setting
+       * gdk/win32/gdkproperty-win32.c: 
+       * gdk/x11/gdksettings.c: ...and back it by a Gtk/IMModule X setting.
+
+       * gtk/gtkimmodule.[hc]: 
+       * gtk/gtkimmulticontext.[hc]: When determining the default context,
+       look at the gtk-im-module setting, and listen for changes to the
+       setting.  (#502446, Akira Tagoh)
+
 2007-12-17  Kristian Rietveld  <kris@imendio.com>
 
        * gtk/gtktooltip.c (gtk_tooltip_finalize),
index e9602ab5e9fa570e731ac54c8db572e8c24a4671..8cd21796a1e105958bb3d0f10bcd598487e14dec 100644 (file)
@@ -1,3 +1,7 @@
+2007-12-17  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/running.sgml: Mention the Gtk/IMModule XSetting.
+
 2007-12-12  Matthias Clasen  <mclasen@redhat.com>
 
        * gdk/gdk-docs.sgml:
index 206e470b7aa97cc61f1996a612f139c15890b54d..c5d1c1017add2396e5b89929705b649779e2ae5a 100644 (file)
@@ -242,7 +242,10 @@ additional environment variables.
 
   <para>
     Specifies an IM module to use in preference to the one determined
-    from the locale. 
+    from the locale.  If this isn't set and you are running on the system
+    that enables <literal>XSETTINGS</literal> and has a value in
+    <literal>Gtk/IMModule</literal>, that will be used for the default
+    IM module.
   </para>
 </formalpara>
 
index f4a409a4aad881daeb08b3d9146a7e78fd140940..1102f8850ece9cc26d782378555074fcb2d21aaf 100644 (file)
@@ -353,6 +353,7 @@ gdk_property_delete (GdkWindow *window,
   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
+  { "Gtk/IMModule", "gtk-im-module" },
   { "Net/CursorBlink", "gtk-cursor-blink" },
   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
   { "Net/ThemeName", "gtk-theme-name" },
index 3e62095abc12a04f39a25db7da39ab9ab7927767..6ef672e2ff652eb18d1170d7725569356858dcc4 100644 (file)
@@ -68,7 +68,9 @@ static const char gdk_settings_names[] =
   "Gtk/TouchscreenMode\0"     "gtk-touchscreen-mode\0"
   "Gtk/EnableAccels\0"        "gtk-enable-accels\0"
   "Gtk/EnableMnemonics\0"     "gtk-enable-mnemonics\0"
-  "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0";
+  "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0"
+  "Gtk/IMModule\0"            "gtk-im-module\0";
+
 
 static const struct
 {
@@ -113,5 +115,6 @@ static const struct
   { 1285, 1305 },
   { 1326, 1343 },
   { 1361, 1381 },
-  { 1402, 1430 }
+  { 1402, 1430 },
+  { 1460, 1473 }
 };
index 52d86d670a1c7e3ea6e98b14dd5142b260f55ec2..9229504ca9d1add3e02f531225066787c5037502 100644 (file)
@@ -37,6 +37,8 @@
 #include <pango/pango-utils.h>
 #include "gtkimmodule.h"
 #include "gtkimcontextsimple.h"
+#include "gtksettings.h"
+#include "gtkmain.h"
 #include "gtkrc.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -418,7 +420,7 @@ _gtk_im_module_list (const GtkIMContextInfo ***contexts,
 #endif
                GtkIMContextInfo simple_context_info = {
     SIMPLE_ID,
-    N_("Default"),
+    N_("Simple"),
     GETTEXT_PACKAGE,
 #ifdef GTK_LOCALEDIR
     GTK_LOCALEDIR,
@@ -546,17 +548,15 @@ match_locale (const gchar *locale,
 
 /**
  * _gtk_im_module_get_default_context_id:
- * @locale: a locale id in the form 'en_US'
+ * @client_window: a window
  * 
- * Return the context_id of the best IM context type
- * for the given locale ID.
+ * Return the context_id of the best IM context type 
+ * for the given window.
  * 
  * Return value: the context ID (will never be %NULL)
- *    the value is newly allocated and must be freed
- *    with g_free().
  **/
 const gchar *
-_gtk_im_module_get_default_context_id (const gchar *locale)
+_gtk_im_module_get_default_context_id (GdkWindow *client_window)
 {
   GSList *tmp_list;
   const gchar *context_id = NULL;
@@ -564,6 +564,8 @@ _gtk_im_module_get_default_context_id (const gchar *locale)
   gint i;
   gchar *tmp_locale, *tmp;
   const gchar *envvar;
+  GdkScreen *screen;
+  GtkSettings *settings;
       
   if (!contexts_hash)
     gtk_im_module_initialize ();
@@ -571,12 +573,41 @@ _gtk_im_module_get_default_context_id (const gchar *locale)
   envvar = g_getenv ("GTK_IM_MODULE");
   if (envvar &&
       (strcmp (envvar, SIMPLE_ID) == 0 ||
-       g_hash_table_lookup (contexts_hash, envvar)))
-    return g_strdup (envvar);
+       g_hash_table_lookup (contexts_hash, envvar))) 
+    return envvar;
+
+  /* Check if the certain immodule is set in XSETTINGS.
+   */
+  if (client_window != NULL && GDK_IS_DRAWABLE (client_window))
+    {
+      screen = gdk_drawable_get_screen (GDK_DRAWABLE (client_window));
+      if (screen)
+        settings = gtk_settings_get_for_screen (screen);
+      else
+        settings = gtk_settings_get_default ();
+
+      g_object_get (G_OBJECT (settings), "gtk-im-module", &tmp, NULL);
+      if (tmp)
+        {
+          if (strcmp (tmp, SIMPLE_ID) == 0)
+            context_id = SIMPLE_ID;
+          else 
+            {
+              GtkIMModule *module;
+              module = g_hash_table_lookup (contexts_hash, tmp);
+              if (module)
+                context_id = module->contexts[0]->context_id;
+            }
+          g_free (tmp);
+
+                 if (context_id) 
+            return context_id;
+        }
+    }
 
   /* Strip the locale code down to the essentials
    */
-  tmp_locale = g_strdup (locale);
+  tmp_locale = _gtk_get_lc_ctype ();
   tmp = strchr (tmp_locale, '.');
   if (tmp)
     *tmp = '\0';
@@ -589,7 +620,7 @@ _gtk_im_module_get_default_context_id (const gchar *locale)
     {
       GtkIMModule *module = tmp_list->data;
      
-      for (i=0; i<module->n_contexts; i++)
+      for (i = 0; i < module->n_contexts; i++)
        {
          const gchar *p = module->contexts[i]->default_locales;
          while (p)
@@ -612,5 +643,5 @@ _gtk_im_module_get_default_context_id (const gchar *locale)
 
   g_free (tmp_locale);
   
-  return g_strdup (context_id ? context_id : SIMPLE_ID);
+  return context_id ? context_id : SIMPLE_ID;
 }
index d58ef15678b5ff04a3c31b65ca59183d199a79b1..a6e3a2d3617cb08789bce798ced1aee3c169425b 100644 (file)
@@ -38,10 +38,10 @@ struct _GtkIMContextInfo
 
 /* Functions for use within GTK+
  */
-void          _gtk_im_module_list                   (const GtkIMContextInfo ***contexts,
-                                                   guint                    *n_contexts);
-GtkIMContext *_gtk_im_module_create                 (const gchar             *context_id);
-const gchar * _gtk_im_module_get_default_context_id (const gchar             *lang);
+void           _gtk_im_module_list                   (const GtkIMContextInfo ***contexts,
+                                                     guint                    *n_contexts);
+GtkIMContext * _gtk_im_module_create                 (const gchar              *context_id);
+const gchar  * _gtk_im_module_get_default_context_id (GdkWindow                *client_window);
 
 /* The following entry points are exported by each input method module
  */
index 7d37cd795feb84c80f20b80e12b2ef592610ad4f..484ae51e6da3e0ce4a1edad6d39eb9f1eb4ab280 100644 (file)
@@ -85,6 +85,7 @@ static gboolean gtk_im_multicontext_delete_surrounding_cb   (GtkIMContext      *
                                                             gint               n_chars,
                                                             GtkIMMulticontext *multicontext);
 
+static const gchar *user_context_id = NULL;
 static const gchar *global_context_id = NULL;
 
 G_DEFINE_TYPE (GtkIMMulticontext, gtk_im_multicontext, GTK_TYPE_IM_CONTEXT)
@@ -141,6 +142,7 @@ gtk_im_multicontext_finalize (GObject *object)
   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (object);
   
   gtk_im_multicontext_set_slave (multicontext, NULL, TRUE);
+  g_free (multicontext->context_id);
 
   G_OBJECT_CLASS (gtk_im_multicontext_parent_class)->finalize (object);
 }
@@ -224,35 +226,68 @@ gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
     {
       GtkIMContext *slave;
 
-      if (!global_context_id)
-       {
-         gchar *locale = _gtk_get_lc_ctype ();
-         global_context_id = _gtk_im_module_get_default_context_id (locale);
-         g_free (locale);
-       }
-       
+      if (!global_context_id) 
+        {
+          if (user_context_id)
+            global_context_id = user_context_id;
+          else
+            global_context_id = _gtk_im_module_get_default_context_id (multicontext->priv->client_window);
+        }
       slave = _gtk_im_module_create (global_context_id);
       gtk_im_multicontext_set_slave (multicontext, slave, FALSE);
       g_object_unref (slave);
 
-      multicontext->context_id = global_context_id;
+      multicontext->context_id = g_strdup (global_context_id);
     }
 
   return multicontext->slave;
 }
 
+static void
+im_module_setting_changed (GtkSettings *settings, 
+                           gpointer     data)
+{
+  global_context_id = NULL;
+}
+
+
 static void
 gtk_im_multicontext_set_client_window (GtkIMContext *context,
                                       GdkWindow    *window)
 {
   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
-  
-  GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
+  GtkIMContext *slave; 
+  GdkScreen *screen; 
+  GtkSettings *settings;
+  gboolean connected;
 
   multicontext->priv->client_window = window;
-  
+
+  slave = gtk_im_multicontext_get_slave (multicontext);
+
   if (slave)
     gtk_im_context_set_client_window (slave, window);
+
+  if (window == NULL) 
+    return;
+   
+  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+  if (screen)
+    settings = gtk_settings_get_for_screen (screen);
+  else
+    settings = gtk_settings_get_default ();
+
+  connected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (settings),
+                                                  "gtk-im-module-connected"));
+  if (!connected) 
+    {
+      g_signal_connect (settings, "notify::gtk-im-module",
+                        G_CALLBACK (im_module_setting_changed), NULL);
+      g_object_set_data (G_OBJECT (settings), "gtk-im-module-connected",
+                         GINT_TO_POINTER (TRUE));
+
+      global_context_id = NULL;  
+    }
 }
 
 static void
@@ -298,7 +333,8 @@ gtk_im_multicontext_focus_in (GtkIMContext   *context)
    * using before, get rid of the old slave and create a new one
    * for the new global context type.
    */
-  if (!multicontext->context_id ||
+  if (multicontext->context_id == NULL || 
+      global_context_id == NULL ||
       strcmp (global_context_id, multicontext->context_id) != 0)
     gtk_im_multicontext_set_slave (multicontext, NULL, FALSE);
 
@@ -459,7 +495,8 @@ activate_cb (GtkWidget         *menuitem,
 
       gtk_im_context_reset (GTK_IM_CONTEXT (context));
       
-      global_context_id = id;
+      user_context_id = id;
+      global_context_id = NULL;
       gtk_im_multicontext_set_slave (context, NULL, FALSE);
     }
 }
@@ -500,12 +537,22 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
   const GtkIMContextInfo **contexts;
   guint n_contexts, i;
   GSList *group = NULL;
+  GtkWidget *menuitem;
   
+  menuitem = gtk_radio_menu_item_new_with_label (group, Q_("input method menu|System"));
+  if (!user_context_id)
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
+  group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
+  g_object_set_data (G_OBJECT (menuitem), I_("gtk-context-id"), NULL);
+  g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), context);
+
+  gtk_widget_show (menuitem);
+  gtk_menu_shell_append (menushell, menuitem);
+
   _gtk_im_module_list (&contexts, &n_contexts);
 
-  for (i=0; i < n_contexts; i++)
+  for (i = 0; i < n_contexts; i++)
     {
-      GtkWidget *menuitem;
       const gchar *translated_name;
 #ifdef ENABLE_NLS
       if (contexts[i]->domain && contexts[i]->domain[0])
@@ -562,11 +609,9 @@ gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
       menuitem = gtk_radio_menu_item_new_with_label (group,
                                                     translated_name);
       
-      if ((global_context_id == NULL && group == NULL) ||
-          (global_context_id &&
-           strcmp (contexts[i]->context_id, global_context_id) == 0))
-        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
-                                        TRUE);
+      if ((user_context_id &&
+           strcmp (contexts[i]->context_id, user_context_id) == 0))
+        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
       
       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
       
index d80b81d650be9bb71e12aa956469fbf30e8be965..aa410f172cf09391f78eb904cb734202b7f2aa28 100644 (file)
@@ -45,7 +45,7 @@ struct _GtkIMMulticontext
 
   GtkIMMulticontextPrivate *priv;
 
-  const gchar *context_id;
+  gchar *context_id;
 };
 
 struct _GtkIMMulticontextClass
index 8fdcfb9a377c36c7e371308f1f2aad25f089289a..3081e8711a9b9374fa36eeeb5748029c36c0c53f 100644 (file)
@@ -106,7 +106,8 @@ enum {
   PROP_PRINT_PREVIEW_COMMAND,
   PROP_ENABLE_MNEMONICS,
   PROP_ENABLE_ACCELS,
-  PROP_RECENT_FILES_LIMIT
+  PROP_RECENT_FILES_LIMIT,
+  PROP_IM_MODULE
 };
 
 
@@ -805,6 +806,20 @@ gtk_settings_class_init (GtkSettingsClass *class)
                                                               GTK_PARAM_READWRITE),
                                             NULL);
   g_assert (result == PROP_RECENT_FILES_LIMIT);
+
+  /**
+   * GtkSettings:gtk-im-module:
+   *
+   * Which IM module should be used by default.
+   */
+  result = settings_install_property_parser (class,
+                                            g_param_spec_string ("gtk-im-module",
+                                                                 P_("Default IM module"),
+                                                                 P_("Which IM module should be used by default"),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                            NULL);
+  g_assert (result == PROP_IM_MODULE);
 }
 
 static void